#ifndef AVALON_LOCKRELEASE_HPP
#define AVALON_LOCKRELEASE_HPP
#include <boost/noncopyable.hpp>
#include "Avalon/Threading/Threading.hpp"

namespace Avalon {
namespace Threading {

  /*! \class LockRelease
   *  \brief Releases a lock, locking it again upon destruction.
   */
  template<typename Lockable>
  class LockRelease : private boost::noncopyable {
    public:

      //! Constructs a LockRelease, invoking a lock's unlock method.
      /*!
        \param lock The lock to release.
      */
      LockRelease(Lockable& lock)
          : m_lock(lock),
            m_isReleased(true) {
        lock.unlock();
      }

      ~LockRelease() {
        if(m_isReleased) {
          m_lock.lock();
        }
      }

      //! Acquires the lock.
      void Acquire() {
        if(m_isReleased) {
          m_lock.lock();
          m_isReleased = false;
        }
      }

      //! Releases the lock.
      void Release() {
        if(m_isReleased) {
          return;
        }
        m_lock.unlock();
        m_isReleased = true;
      }

    private:
      Lockable& m_lock;
      bool m_isReleased;
  };
}
}

#endif // AVALON_LOCKRELEASE_HPP
